package com.bestom.communication.services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;

import com.bestom.communication.callbacks.IGetMessageCallBack;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.util.Arrays;

public class MQTTService extends Service {

    private MqttAndroidClient client;
    private MqttConnectOptions conOpt;
    private IGetMessageCallBack mIGetMessageCallBack;

    @Override
    public IBinder onBind(Intent intent) {
        return new CustomBinder();
    }

    public class CustomBinder extends Binder {

        public MQTTService getService(){
            return MQTTService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    public void connectionMQtt(String host, String clientId, String username, String password, IGetMessageCallBack iGetMessageCallBack) {

        mIGetMessageCallBack = iGetMessageCallBack;
        // 服务器地址（协议+地址+端口号）
        client = new MqttAndroidClient(this, host, clientId);
        // 设置MQTT监听并且接受消息
        client.setCallback(mqttCallback);

        conOpt = new MqttConnectOptions();
        // 清除缓存
        conOpt.setCleanSession(true);
        // 设置超时时间，单位：秒
        conOpt.setConnectionTimeout(10);
        // 心跳包发送间隔，单位：秒
        conOpt.setKeepAliveInterval(30);
        // 用户名
        conOpt.setUserName(username);
        // 密码
        conOpt.setPassword(password.toCharArray());

        boolean doConnect = true;

        // last will message
        String message = "{\"title\":\"Last Will\", \"clientId\":\"" + clientId + "\", \"status\": \"disconnect\", \"message\": \"The client disconnects\"}";
        String topic = "Client/DisconnectReport";

        /* 最后的遗嘱
         * MqTT本身就是为信号不稳定的网络设计的，所以难免一些客户端会无故的和Broker断开连接。
         * 当客户端连接到Broker时，可以指定LWT，Broker会定期检测客户端是否有异常。
         * 当客户端异常掉线时，Broker就往连接时指定的topic里推送当时指定的LWT消息。
         * */
        try {
            conOpt.setWill(topic, message.getBytes(), 0, false);
        } catch (Exception e) {
            doConnect = false;
            mIMqttActionListener.onFailure(null, e);
        }

        if (doConnect) {
            doClientConnection();
        }

    }
    public void disConnectMQtt(){
        try {
            if (client.isConnected()) client.disconnect();
            else mHandler.removeCallbacks(mRunnable);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /** 连接MQTT服务器 */
    private void doClientConnection() {
        if (!client.isConnected() && isConnectIsNormal()) {
            try {
                client.connect(conOpt, null, mIMqttActionListener);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

    }
    public boolean mqttIsConnect(){
        if (client == null) return false;
        try {
            return client.isConnected();
        }catch (Exception e){
            return false;
        }
    }

    /**MqTT是否连接成功*/
    private final IMqttActionListener mIMqttActionListener = new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken arg0) {
            mIGetMessageCallBack.setSuccess("MQtt 连接成功");
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            mIGetMessageCallBack.setFail("MQtt 连接失败, 10秒后将尝试重连");
            // 连接失败，重连
            mHandler.postDelayed(mRunnable,10000);
        }
    };

    public void subscribe(String topic) {
        try {
            // 订阅myTopic主题
            if (client != null && client.isConnected()) {
                client.subscribe(topic, 1);
                mIGetMessageCallBack.setMessage("订阅 " + topic + " 主题成功");
            }else {
                mIGetMessageCallBack.setMessage("MQtt 未连接，订阅主题失败");
            }
        } catch (MqttException e) {
            mIGetMessageCallBack.setMessage("订阅 " + topic + " 主题失败");
        }
    }

    public void publish(String topic, String msg){

        try {
            if (client != null){
                client.publish(topic, msg.getBytes(), 0, false);
                mIGetMessageCallBack.setMessage("推送成功--->" + topic + "#" + msg);
            }else {
                mIGetMessageCallBack.setMessage("客户端未连接，推送失败--->" + topic + "#" + msg);
            }
        } catch (Exception e) {
            mIGetMessageCallBack.setMessage("MQtt 异常，推送失败--->" + topic + "#" + msg);
        }
    }

    private final Handler mHandler = new Handler();
    private final Runnable mRunnable = this::doClientConnection;

    /**MqTT监听并且接受消息*/
    private final MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) {

            String str = "MQtt 接收--->" + topic + "#" + new String(message.getPayload());
            if (mIGetMessageCallBack != null) mIGetMessageCallBack.setMessage(str);
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {

        }

        @Override
        public void connectionLost(Throwable arg0) {
            // 失去连接，重连
//            doClientConnection();
            mIGetMessageCallBack.setMessage("MQtt 已断开连接");
        }
    };

    /** 判断网络是否连接 */
    private boolean isConnectIsNormal() {
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            String name = info.getTypeName();
            mIGetMessageCallBack.setMessage("MQTT连接使用当前网络名称：" + name);
            return true;
        } else {
            mIGetMessageCallBack.setMessage("未检测到可用网络，MQTT连接失败，10秒后将尝试重连");
            /*没有可用网络的时候，延迟10秒再尝试重连*/
            mHandler.postDelayed(mRunnable, 10000);
            return false;
        }
    }

    @Override
    public void onDestroy() {
        try {
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
        stopSelf();
        super.onDestroy();
    }
}